//
// Created by tview on 2021/7/29.
//

#ifndef SIMPLE_PLAYER_MODULEFACTORY_H
#define SIMPLE_PLAYER_MODULEFACTORY_H

#ifdef TAG
#undef TAG
#define TAG "moduleFactory"
#endif

#include <TsDemux.h>
#include <MkvDemux.h>
#include "MediaPlayer.h"
#include "NDKDemux.h"
#include "NDKDecoder.h"
#include "NDKRender.h"
#include "Demux.h"
#include "FFMPEGDemux.h"

template<class T>
class FactortyNode {
public:

    virtual int getScore() { return 0; };

    FactortyNode *getNext() {
        return next;
    }

    void setNext(FactortyNode *node) {
        next = node;
    }

    virtual shared_ptr<T> Factory(weak_ptr<MediaPlayer> player) { return nullptr; }

private:
    FactortyNode *next = nullptr;
};

class Demux;

template<class E>
class ModuleManager {
public:

    ModuleManager(){
    }
public:
    void registerFactory(FactortyNode<E> *node) {
        FactortyNode<E> *ptr = factortyList;
        FactortyNode<E> *tmp;
        if (ptr == nullptr) {
            factortyList = node;
            LOGD("first add module (%s) sucess",typeid(*(node)).name());
            return;
        }
        if (ptr->getScore() < node->getScore()){
            node->setNext(ptr);
            factortyList = node;
            return;
        }

        while (true) {
            if (ptr->getScore() >= node->getScore()) {
                if (ptr->getNext() == nullptr){
                    ptr->setNext(node);
                    return;
                }
                //这是插入值比后值大，即可插入。
                if (ptr->getNext()->getScore() < node->getScore()) {
//                    LOGD("add module (%s) sucess",typeid(*(node)).name());
                    tmp = ptr->getNext();
                    ptr->setNext(node);
                    node->setNext(tmp);
                    return;
                }
//            } else{ //不可能发生
//                tmp
//                node->setNext(ptr);

            }

            ptr = ptr->getNext(); //移动到下一个结点
        }

    }

    template<typename T1>
    shared_ptr<E> getModule(shared_ptr<MediaPlayer> mediaPlayer, T1 path) {

        FactortyNode<E> *ptr = factortyList;

        while (ptr) {
            shared_ptr<E> module = ptr->Factory(mediaPlayer);
            if (module) {
                if (module->Open(path))
                    LOGD("load module (%s) sucess",typeid(*(module.get())).name());
                    return module;
            }
            ptr = ptr->getNext();
        }
        return nullptr;
    }

private:
    FactortyNode<E> *factortyList;
};


class NdkDemuxFactory : public FactortyNode<Demux> {

    int getScore() override {
        return 10;
    }

    shared_ptr<Demux> Factory(weak_ptr<MediaPlayer> player) override {
        return make_shared<NDKDemux>(player);
    }
};

class FFMPEGDemuxFactory : public FactortyNode<Demux> {

    int getScore() override {
        return 11;
    }

    shared_ptr<Demux> Factory(weak_ptr<MediaPlayer> player) override {
        return make_shared<FFMPEGDemux>(player);
    }
};

class TsDemuxFactory : public FactortyNode<Demux> {

    int getScore() override {
        return 12;
    }

    shared_ptr<Demux> Factory(weak_ptr<MediaPlayer> player) override {
        return make_shared<TsDemux>(player);
    }
};

class MKVDemuxFactory : public FactortyNode<Demux> {

    int getScore() override {
        return 13;
    }

    shared_ptr<Demux> Factory(weak_ptr<MediaPlayer> player) override {
        return make_shared<MkvDemux>(player);
    }
};

class NdkDecoderFactory : public FactortyNode<VideoDecoder> {

    int getScore() override {
        return 10;
    }

    shared_ptr<VideoDecoder> Factory(weak_ptr<MediaPlayer> player) override {
        return make_shared<NDKDecoder>(player);
    }
};


class NdkRenderFactory : public FactortyNode<VideoRender> {

    int getScore() override {
        return 10;
    }

    shared_ptr<VideoRender> Factory(weak_ptr<MediaPlayer> player) override {
        return make_shared<NDKRender>(player);
    }
};

#endif //SIMPLE_PLAYER_MODULEFACTORY_H
